#define _MENUGEN_C_

#include <avr/io.h>
#include <avr/interrupt.h>
#include <string.h>
#include <util/delay.h>
#include <math.h>
#include <stdlib.h>
#include <avr/pgmspace.h>

#include "config.h"
#include "typedefs.h"
#include "menuGen.h"
#include "TIMEBASE.H"
#include "t6963c.h"
#include "buttons.h"
#include "sensors.h"
#include "dcf77.h"

#include "pcf8574.h"

/**
possible menustructure:

settings - clock (modify clock)
  |      - alarms (modify alarms)
main     - misc (modify settings: backlight timeout, temperature controller, etc)
  +
information - sensor status
            - system information
*/

extern t_appSettings appSettings;
extern t_uartFifo uartTxBuf;

unsigned char ucCurMenuPage = 0xFF; // for startup
unsigned char ucNextMenuPage = 0;
unsigned char ucNrSubPage = 0;
unsigned char ucMenuChanged = 0;
unsigned char ucBgLightState = 0;
unsigned int uiBgChgTime = 0;
signed int siBtnPMValue = 0;


#define C_PAGE_MAIN 0x00
#define C_PAGE_DATE_TIME 0x01
#define C_PAGE_DATE_TIME_EDIT_YEAR 0x02
#define C_PAGE_DATE_TIME_EDIT_MONTH 0x03
#define C_PAGE_DATE_TIME_EDIT_DAY 0x04
#define C_PAGE_DATE_TIME_EDIT_HOUR 0x05
#define C_PAGE_DATE_TIME_EDIT_MINUTE 0x06
#define C_PAGE_DATE_TIME_EDIT_SECOND 0x07

#define C_PAGE_TEMP_LOGGING 0x80

#define C_MENUPAGES 9
t_menuPage menuPage[C_MENUPAGES] = {
	{
		C_PAGE_MAIN,		// pageID
		C_PAGE_DATE_TIME,	// next page
		C_PAGE_TEMP_LOGGING,		// previous page
		TRUE				// clear page on transition
	},
	{
		C_PAGE_DATE_TIME, 
		C_PAGE_DATE_TIME_EDIT_YEAR, 
		C_PAGE_MAIN,
		TRUE
	},
	{
		C_PAGE_DATE_TIME_EDIT_YEAR, 
		C_PAGE_DATE_TIME_EDIT_MONTH, 
		C_PAGE_DATE_TIME,
		TRUE
	},
	{
		C_PAGE_DATE_TIME_EDIT_MONTH, 
		C_PAGE_DATE_TIME_EDIT_DAY, 
		C_PAGE_DATE_TIME,
		TRUE
	},
	{
		C_PAGE_DATE_TIME_EDIT_DAY, 
		C_PAGE_DATE_TIME_EDIT_HOUR, 
		C_PAGE_DATE_TIME,
		TRUE
	},
	{
		C_PAGE_DATE_TIME_EDIT_HOUR, 
		C_PAGE_DATE_TIME_EDIT_MINUTE, 
		C_PAGE_DATE_TIME,
		TRUE
	},
	{
		C_PAGE_DATE_TIME_EDIT_MINUTE, 
		C_PAGE_DATE_TIME_EDIT_SECOND, 
		C_PAGE_DATE_TIME,
		TRUE
	},
	{
		C_PAGE_DATE_TIME_EDIT_SECOND, 
		C_PAGE_DATE_TIME, 
		C_PAGE_DATE_TIME,
		TRUE
	},
	{
		C_PAGE_TEMP_LOGGING, 
		C_PAGE_MAIN, 
		C_PAGE_MAIN,
		TRUE
	}
};

unsigned char getPageID(unsigned char searchID){
	for (unsigned int i = 0; i < C_MENUPAGES; i++){
		if (menuPage[i].pageID == searchID) return i;
	}
	return 0;
}

void menuGeneratorInit(void){
	// GLCD works only with VCC = 5V@16MHz, Display works with 4MHz@3.3V
    glcd_setup();
    glcd_init();
    glcd_clear_text();
    glcd_clear_graph();
}

void menuGenerator(void)
{
// Handler to update display
    static unsigned int uiTimer = 0;
    unsigned char s[32];

// Check for pressed buttons, apply menu transitions
    if (ucCurMenuPage == ucNextMenuPage)
    {
        // Check Button 1, show next menu page
        if (buttons.btn[0] > 5)
        {
			ucNextMenuPage = menuPage[getPageID(ucCurMenuPage)].nextPage;
        }

        // Check Button 2, go back one page
        if (buttons.btn[1] > 5)
        {
			ucNextMenuPage = menuPage[getPageID(ucCurMenuPage)].prevPage;
        }
    }
// Backlight handler
    if (ucBgLightState == 0)
    {
        if (buttons.btn[0] > 1 || buttons.btn[1] > 1|| buttons.btn[2] > 1 || buttons.btn[3] > 1)
        {
            BACKLIGHT_ON();
            ucBgLightState = 1;
            uiBgChgTime = timer_freeze_ticks();
        }
    }
    else
    {
        if (buttons.btn[0] > 1 || buttons.btn[1] > 1|| buttons.btn[2] > 1 || buttons.btn[3] > 1)
        {
            uiBgChgTime = timer_freeze_ticks();
        }
        else if (timer_timeover_ticks(uiBgChgTime,appSettings.uiBgLightTimeout))
        {
            BACKLIGHT_OFF();
            ucBgLightState = 0;
        }
    }

// draw menu, refresh every 50 ticks
    if (timer_timeover_ticks(uiTimer,50))
    {
        if (ucNextMenuPage != ucCurMenuPage)
        {
            glcd_clear_text();
            glcd_clear_graph();
#ifdef _DEBUG_
            sprintf((char*)s,"%02X",ucNextMenuPage);
            glcd_print(19,0,(char*)s);
#endif
        }
        switch (ucNextMenuPage)
        {

            // Menupage 0, mainpage
        case C_PAGE_MAIN:

            // Line 7:
            sprintf((char*)s, "%02d:%02d:%02d", (unsigned int)systemTime.hour,systemTime.minute,systemTime.second );
            glcd_print(2,6,(char*)s);
            // Line 8:
            sprintf((char*)s, "20%02d-%02d-%02d", systemDate.ucYear, systemDate.ucMonth, systemDate.ucDay );
            glcd_print(0,7,(char*)s);
			
			// draw static image only if pageID has changed
			if (ucNextMenuPage != ucCurMenuPage){
				glcd_line(63,0,63,63,TRUE);
				glcd_line(64,0,64,63,TRUE);
			
				// draw house
				glcd_line(71,30,71,63,TRUE);
				glcd_line(71,30,103,30,TRUE);
				glcd_line(103,30,103,63,TRUE);
				glcd_line(71,63,103,63,TRUE);
				// draw roof
				glcd_line(67,33,87,18,TRUE);
				glcd_line(107,33,87,18,TRUE);
			
				// draw collector
				glcd_line(100,25,92,19,TRUE);
			
				// draw sun
				glcd_circle(120,7,4,TRUE);
				glcd_line(116,7,110,7,TRUE);
				glcd_line(120,11,120,17,TRUE);
				glcd_line(117,10,113,14,TRUE);
				glcd_line(123,10,127,14,TRUE);
				glcd_line(117,4,113,0,TRUE);
				glcd_line(120,3,120,0,TRUE);
				glcd_line(123,4,127,0,TRUE);
				glcd_line(124,7,127,7,TRUE);
			
				// draw boiler
				glcd_line(75,36,75,57,TRUE);
				glcd_line(77,34,97,34,TRUE);
				glcd_line(99,36,99,57,TRUE);
				glcd_line(77,59,97,59,TRUE);
			
				glcd_pixel(76,35,TRUE);
				glcd_pixel(98,35,TRUE);
				glcd_pixel(98,58,TRUE);
				glcd_pixel(76,58,TRUE);
			}				
			
            sprintf((char*)s, "%2dC", tempSensorsRemote.sSensor[0].siTemp/10 );
            glcd_print(13,5,(char*)s);


            break;

            // menupage 3
        case C_PAGE_DATE_TIME: // Show date+time
        case C_PAGE_DATE_TIME_EDIT_YEAR: // modify year
        case C_PAGE_DATE_TIME_EDIT_MONTH: // modify month
        case C_PAGE_DATE_TIME_EDIT_DAY: // modify day
        case C_PAGE_DATE_TIME_EDIT_HOUR: // modify hour
        case C_PAGE_DATE_TIME_EDIT_MINUTE: // modify minute
        case C_PAGE_DATE_TIME_EDIT_SECOND: // modify second
        {
            unsigned char ucCursorPos = 0;
            if (ucNextMenuPage == C_PAGE_DATE_TIME_EDIT_YEAR) ucCursorPos = 1;
            else if (ucNextMenuPage == C_PAGE_DATE_TIME_EDIT_MONTH) ucCursorPos = 2;
            else if (ucNextMenuPage == C_PAGE_DATE_TIME_EDIT_DAY) ucCursorPos = 3;
            else if (ucNextMenuPage == C_PAGE_DATE_TIME_EDIT_HOUR) ucCursorPos = 4;
            else if (ucNextMenuPage == C_PAGE_DATE_TIME_EDIT_MINUTE) ucCursorPos = 5;
            else if (ucNextMenuPage == C_PAGE_DATE_TIME_EDIT_SECOND) ucCursorPos = 6;

            signed char scModValue = 0;
            if (buttons.btn[2] > 5) scModValue = 1;
            if (buttons.btn[3] > 5) scModValue--;
            switch(ucCursorPos)
            {
            case 1:
				if (scModValue != 0) dateModify((t_date*)&systemDate,2,scModValue);
                break;

            case 2:
				if (scModValue != 0) dateModify((t_date*)&systemDate,1,scModValue);
                break;

            case 3:
				if (scModValue != 0) dateModify((t_date*)&systemDate,0,scModValue);
				break;

            case 4:
				if (scModValue != 0){
					if (systemTime.hour == 23 && scModValue == 1) systemTime.hour = 0;
					else if (systemTime.hour == 0 && scModValue == -1) systemTime.hour = 23;
					else systemTime.hour += scModValue;
				}
				break;

            case 5:
				if (scModValue != 0){
					if (systemTime.minute == 59 && scModValue == 1) systemTime.minute = 0;
					else if (systemTime.minute == 0 && scModValue == -1) systemTime.minute = 59;
					else systemTime.minute += scModValue;
				}
				break;

            case 6:
				if (scModValue != 0){
					if (systemTime.second == 59 && scModValue == 1) systemTime.second = 0;
					else if (systemTime.second == 0 && scModValue == -1) systemTime.second = 59;
					else systemTime.second += scModValue;
				}
				break;
            }

            // Line 2:
            if (ucCursorPos > 0 && ucCursorPos <= 3) glcd_print((5+ucCursorPos*3),1,"**");
            // Line 3:
            sprintf((char*)s, "Date: 20%02d-%02d-%02d", systemDate.ucYear, systemDate.ucMonth, systemDate.ucDay);
            glcd_print(0,2,(char*)s);
            // Line 4:
            if (ucCursorPos > 3 && ucCursorPos <= 6) glcd_print((3+(ucCursorPos-3)*3),3,"**");
            // Line 5:
            sprintf((char*)s, "Time: %02d:%02d:%02d", (unsigned int)systemTime.hour, systemTime.minute, systemTime.second);
            glcd_print(0,4,(char*)s);
            // Line 8:
            sprintf((char*)s, "20%02d-%02d-%02d %02d:%02d:%02d", dcf77Date.ucYear, dcf77Date.ucMonth, dcf77Date.ucDay, (unsigned int)dcf77Time.hour, dcf77Time.minute, dcf77Time.second);
            glcd_print(0,7,(char*)s);
        }

        break;
		
        case C_PAGE_TEMP_LOGGING: // display temp log
		if ((ucCurMenuPage != ucNextMenuPage) || (tempLogs.fUpdateGraph == 1)){
	  
			// generate graphic
			glcd_clear_graph();
			//glcd_clear_text();
			
			glcd_print(0,1,"70C");
			glcd_print(0,6,"10C");
			glcd_line(18,11,127,11,TRUE);
			glcd_line(18,51,127,51,TRUE);
			
			for (unsigned char i = 0; i<55; i++){
				unsigned int ucHeight = 0;
				
				if (tempLogs.logValues[i] >= 10) ucHeight = ((tempLogs.logValues[i]-10)*2)/3;
				
				glcd_box(18+i*2,51,19+i*2,51-ucHeight,TRUE);
			}
			tempLogs.fUpdateGraph = 0;
			
			//Debug only
			for (unsigned char i = 0; i < 55; i++) Uart_putc_0(tempLogs.logValues[i]);
			Uart_puts_0("\r\n");
		}
		
		break; // Page temp logging

        default:
            // Goto page 0
            ucNextMenuPage = 0;
            ucMenuChanged = 1;
        } //switch

        // Refresh display next interval
        uiTimer = timer_freeze_ticks();
		// save current page
		ucCurMenuPage = ucNextMenuPage;
    } // if timeover
}
